home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 4 / Apprentice-Release4.iso / Source Code / Add-Ons / MPW / MPW dmake 4.0 / dbug / malloc / malloc.c < prev    next >
Encoding:
Text File  |  1995-06-01  |  12.7 KB  |  451 lines  |  [TEXT/KAHL]

  1. /*
  2.  * (c) Copyright 1990 Conor P. Cahill (uunet!virtech!cpcahil).  
  3.  * You may copy, distribute, and use this software as long as this
  4.  * copyright statement is not removed.
  5.  */
  6. #include <stdio.h>
  7. #include <fcntl.h>
  8. #include "malloc.h"
  9. #include "tostring.h"
  10.  
  11. /*
  12.  * Function:    malloc()
  13.  *
  14.  * Purpose:    memory allocator
  15.  *
  16.  * Arguments:    size    - size of data area needed
  17.  *
  18.  * Returns:    pointer to allocated area, or NULL if unable
  19.  *        to allocate addtional data.
  20.  *
  21.  * Narrative:
  22.  *
  23.  */
  24. #ifndef lint
  25. static
  26. char rcs_hdr[] = "$Id: malloc.c,v 1.1 1994/10/06 17:43:12 dvadura Exp $";
  27. #endif
  28.  
  29. extern int      malloc_checking;
  30. char        * malloc_data_start;
  31. char        * malloc_data_end;
  32. struct mlist     * malloc_end;
  33. int          malloc_errfd = 2;
  34. int          malloc_errno;
  35. int          malloc_fatal_level = M_HANDLE_CORE;
  36. struct mlist      malloc_start;
  37. int          malloc_warn_level;
  38. void          malloc_memset();
  39.  
  40. char *
  41. malloc(size)
  42.     unsigned int      size;
  43. {
  44.     char        * func = "malloc";
  45.     char        * getenv();
  46.     void          malloc_fatal();
  47.     void          malloc_init();
  48.     void          malloc_split();
  49.     void          malloc_warning();
  50.     unsigned int      need;
  51.     struct mlist    * oldptr;
  52.     struct mlist    * ptr;
  53.     char        * sbrk();
  54.  
  55.     /*
  56.      * If this is the first call to malloc...
  57.      */
  58.     if( malloc_data_start == (char *) 0 )
  59.     {
  60.         malloc_init();
  61.     }
  62.  
  63.     /*
  64.      * If malloc chain checking is on, go do it.
  65.      */
  66.     if( malloc_checking )
  67.     {
  68.         (void) malloc_chain_check(1);
  69.     }
  70.  
  71.     /*
  72.      * always make sure there is at least on extra byte in the malloc
  73.      * area so that we can verify that the user does not overrun the
  74.      * data area.
  75.      */
  76.     size++;
  77.  
  78.     /*
  79.      * Now look for a free area of memory of size bytes...
  80.      */
  81.     oldptr = NULL;
  82.     for(ptr = &malloc_start; ; ptr = ptr->next)
  83.     {
  84.         /*
  85.          * Since the malloc chain is a forward only chain, any
  86.          * pointer that we get should always be positioned in 
  87.          * memory following the previous pointer.  If this is not
  88.          * so, we must have a corrupted chain.
  89.          */
  90.         if( ptr )
  91.         {
  92.             if( ptr<oldptr )
  93.             {
  94.                 malloc_errno = M_CODE_CHAIN_BROKE;
  95.                 malloc_fatal(func);
  96.                 return(NULL);
  97.             }
  98.             oldptr = ptr;
  99.         }
  100.         else ied int      newsize;
  101.  
  102.     if(     ptr     && ! (inuse_override || (ptr->flag & M_INUSE)) && 
  103.         nextptr && ! (nextptr->flag & M_INUSE) &&
  104.         ((ptr->data+ptr->s.size) == (char *) nextptr) )
  105.     {
  106.         if( malloc_end == nextptr )
  107.         {
  108.             malloc_end = ptr;
  109.         }
  110.         ptr->next = nextptr->next;
  111.         newsize = nextptr->s.size + M_SIZE;
  112.  
  113.         /*
  114.          * if we are to fill and this segment is in use,
  115.          *   fill in with M_FILL newly added space...
  116.           */
  117.  
  118.         if(fill_flag && (ptr->flag & M_INUSE) )
  119.         {
  120.             malloc_memset(ptr->data+ptr->s.size,
  121.                       M_FILL, (int)(nextptr->s.size + M_SIZE));
  122.         }
  123.  
  124.         ptr->s.size += newsize;
  125.         if( ptr->next )
  126.         {
  127.             ptr->next->prev = ptr;
  128.         }
  129.     }
  130.  
  131. } /* malloc_join(... */
  132.  
  133.  
  134. /*
  135.  * The following mess is just to ensure that the versions of these functions in
  136.  * the current library are included (to make sure that we don't accidentaly get 
  137.  * the libc versions. (This is the lazy man's -u ld directive)
  138.  */
  139.  
  140. void free();
  141. int strcmp();
  142. int memcmp();
  143. char    * realloc();
  144.  
  145. void        (*malloc_void_funcs[])() =
  146. {
  147.     free,
  148. };
  149.  
  150. int        (*malloc_int_funcs[])() =
  151. {
  152.     strcmp,
  153.     memcmp,
  154. };
  155.  
  156. char        * (*malloc_char_star_funcs[])() =
  157. {
  158.     realloc,
  159. };
  160.  
  161. /*
  162.  * This is malloc's own memset which is used without checking the parameters.
  163.  */
  164.  
  165. void
  166. malloc_memset(ptr,byte,len)
  167.     char        * ptr;
  168.     char          byte;
  169.     int          len;
  170. {
  171.  
  172.     while(len-- > 0)
  173.     {
  174.         *ptr++ = byte;
  175.     }
  176.  
  177. } /* malloc_memset(... */
  178.  
  179. /*
  180.  * Function:    malloc_fatal()
  181.  *
  182.  * Purpose:    to display fatal error message and take approrpriate action
  183.  *
  184.  * Arguments:    funcname - name of function calling this routine
  185.  *
  186.  * Returns:    nothing of any value
  187.  *
  188.  * Narrative:
  189.  *
  190.  * Notes:    This routine does not make use of any libc functions to build
  191.  *        and/or disply the error message.  This is due to the fact that
  192.  *        we are probably at a point where malloc is having a real problem
  193.  *        and we don't want to call any function that may use malloc.
  194.  */
  195. void
  196. malloc_fatal(funcname)
  197.     char        * funcname;
  198. {
  199.     char          errbuf[128];
  200.     void          exit();
  201.     void          malloc_err_handler();
  202.     extern char    * malloc_err_strings[];
  203.     extern int      malloc_errno;
  204.     extern int      malloc_fatal_level;
  205.     char        * s;
  206.     char        * t;
  207.  
  208.     s = errbuf;
  209.     t = "Fatal error: ";
  210.     while( *s = *t++)
  211.     {
  212.         s++;
  213.     }
  214.     t = funcname;
  215.     while( *s = *t++)
  216.     {
  217.         s++;
  218.     }
  219.  
  220.     t = "(): ";
  221.     while( *s = *t++)
  222.     {
  223.         s++;
  224.     }
  225.  
  226.     t = malloc_err_strings[malloc_errno];
  227.     while( *s = *t++)
  228.     {
  229.         s++;
  230.     }
  231.  
  232.     *(s++) = '\n';
  233.  
  234.     if( write(malloc_errfd,errbuf,(unsigned)(s-errbuf)) != (s-errbuf))
  235.     {
  236.         (void) write(2,"I/O error to error file\n",(unsigned)24);
  237.         exit(110);
  238.     }
  239.     malloc_err_handler(malloc_fatal_level);
  240.  
  241. } /* malloc_fatal(... */
  242.  
  243. /*
  244.  * Function:    malloc_warning()
  245.  *
  246.  * Purpose:    to display warning error message and take approrpriate action
  247.  *
  248.  * Arguments:    funcname - name of function calling this routine
  249.  *
  250.  * Returns:    nothing of any value
  251.  *
  252.  * Narrative:
  253.  *
  254.  * Notes:    This routine does not make use of any libc functions to build
  255.  *        and/or disply the error message.  This is due to the fact that
  256.  *        we are probably at a point where malloc is having a real problem
  257.  *        and we don't want to call any function that may use malloc.
  258.  */
  259. void
  260. malloc_warning(funcname)
  261.     char        * funcname;
  262. {
  263.     char          errbuf[128];
  264.     void          exit();
  265.     void          malloc_err_handler();
  266.     extern char    * malloc_err_strings[];
  267.     extern int      malloc_errno;
  268.     extern int      malloc_warn_level;
  269.     char        * s;
  270.     char        * t;
  271.  
  272.     s = errbuf;
  273.     t = "Warning: ";
  274.     while( *s = *t++)
  275.     {
  276.         s++;
  277.     }
  278.     t = funcname;
  279.     while( *s = *t++)
  280.     {
  281.         s++;
  282.     }
  283.  
  284.     t = "(): ";
  285.     while( *s = *t++)
  286.     {
  287.         s++;
  288.     }
  289.  
  290.     t = malloc_err_strings[malloc_errno];
  291.     while( *s = *t++)
  292.     {
  293.         s++;
  294.     }
  295.  
  296.     *(s++) = '\n';
  297.  
  298.     if( write(malloc_errfd,errbuf,(unsigned)(s-errbuf)) != (s-errbuf))
  299.     {
  300.         (void) write(2,"I/O error to error file\n",(unsigned)24);
  301.         exit(110);
  302.     }
  303.  
  304.     malloc_err_handler(malloc_warn_level);
  305.  
  306. } /* malloc_warning(... */
  307.  
  308. /*
  309.  * Function:    malloc_err_handler()
  310.  *
  311.  * Purpose:    to take the appropriate action for warning and/or fatal 
  312.  *        error conditions.
  313.  *
  314.  * Arguments:    level - error handling level 
  315.  *
  316.  * Returns:    nothing of any value
  317.  *
  318.  * Narrative:
  319.  *
  320.  * Notes:    This routine does not make use of any libc functions to build
  321.  *        and/or disply the error message.  This is due to the fact that
  322.  *        we are probably at a point where malloc is having a real problem
  323.  *        and we don't want to call any function that may use malloc.
  324.  */
  325. void
  326. malloc_err_handler(level)
  327. {
  328.     void          exit();
  329.     void          malloc_dump();
  330.     extern int      malloc_errfd;
  331.  
  332.     if( level & M_HANDLE_DUMP )
  333.     {
  334.         malloc_dump(malloc_errfd);
  335.     }
  336.  
  337.     switch( level & ~M_HANDLE_DUMP )
  338.     {
  339.         /*
  340.          * If we are to drop a core file and exit
  341.          */
  342.         case M_HANDLE_ABORT:
  343.             (void) abort();
  344.             break;
  345.  
  346.         /*
  347.          * If we are to exit..
  348.          */
  349.         case M_HANDLE_EXIT:
  350.             exit(200);
  351.             break;
  352.  
  353. #ifndef __MSDOS__
  354.         /*
  355.          * If we are to dump a core, but keep going on our merry way
  356.          */
  357.         case M_HANDLE_CORE:
  358.             {
  359.                 int      pid;
  360.  
  361.                 /*
  362.                  * fork so child can abort (and dump core)
  363.                  */
  364.                 if( (pid = fork()) == 0 )
  365.                 {
  366.                     (void) write(2,"Child dumping core\n",
  367.                             (unsigned)9);
  368.                     (void) abort();
  369.                 }
  370.  
  371.                 /*
  372.                   * wait for child to finish dumping core
  373.                  */
  374.                 while( wait((int *)0) != pid)
  375.                 {
  376.                 }
  377.  
  378.                 /*
  379.                  * Move core file to core.pid.cnt so 
  380.                  * multiple cores don't overwrite each
  381.                  * other.
  382.                  */
  383.                 if( access("core",0) == 0 )
  384.                 {
  385.                     static int      corecnt;
  386.                     char            filenam[32];
  387.                     filenam[0] = 'c';
  388.                     filenam[1] = 'o';
  389.                     filenam[2] = 'r';
  390.                     filenam[3] = 'e';
  391.                     filenam[4] = '.';
  392.                     (void)tostring(filenam+5,getpid(),
  393.                         5, B_DEC, '0');
  394.                     filenam[10] = '.';
  395.                     (void)tostring(filenam+11,corecnt++,
  396.                         3, B_DEC, '0');
  397.                     filenam[14] = '\0';
  398.                     (void) unlink(filenam);
  399.                     if( link("core",filenam) == 0)
  400.                     {
  401.                         (void) unlink("core");
  402.                     }
  403.                 }
  404.             }
  405. #endif
  406.  
  407.  
  408.         /* 
  409.          * If we are to just ignore the error and keep on processing
  410.          */
  411.         case M_HANDLE_IGNORE:
  412.             break;
  413.  
  414.     } /* switch(... */
  415.  
  416. } /* malloc_err_handler(... */
  417.  
  418. /*
  419.  * $Log: malloc.c,v $
  420.  * Revision 1.1  1994/10/06  17:43:12  dvadura
  421.  * dmake Release Version 4.0, Initial revision
  422.  *
  423.  * Revision 1.1  1994/10/06  03:45:22  dvadura
  424.  * dmake Release Version 4.0, Initial revision
  425.  *
  426.  * Revision 1.1  1992/01/24  03:29:05  dvadura
  427.  * dmake Version 3.8, Initial revision
  428.  *
  429.  * Revision 1.6  90/05/11  00:13:09  cpcahil
  430.  * added copyright statment
  431.  * 
  432.  * Revision 1.5  90/02/25  11:01:18  cpcahil
  433.  * added support for malloc chain checking.
  434.  * 
  435.  * Revision 1.4  90/02/24  21:50:21  cpcahil
  436.  * lots of lint fixes
  437.  * 
  438.  * Revision 1.3  90/02/24  14:51:18  cpcahil
  439.  * 1. changed malloc_fatal and malloc_warn to use malloc_errno and be passed
  440.  *    the function name as a parameter.
  441.  * 2. Added several function headers.
  442.  * 3. Changed uses of malloc_fatal/warning to conform to new usage.
  443.  * 
  444.  * Revision 1.2  90/02/23  18:05:23  cpcahil
  445.  * fixed open of error log to use append mode.
  446.  * 
  447.  * Revision 1.1  90/02/22  23:17:43  cpcahil
  448.  * Initial revision
  449.  * 
  450.  */
  451.